package br.webcrawler.activities.webcrawler.webcrawler;


import br.webcrawler.activities.webcrawler.logs.Logger;
import br.webcrawler.activities.webcrawler.utils.Data;
import br.webcrawler.activities.webcrawler.utils.FileManager;
import br.webcrawler.activities.webcrawler.xml.Constants;
import br.webcrawler.activities.webcrawler.xml.DownloadActivity;

import java.io.File;
import java.util.ArrayList;
import java.util.List;

import javax.swing.JFrame;

import org.openqa.selenium.By;
import org.openqa.selenium.JavascriptExecutor;
import org.openqa.selenium.NoSuchElementException;
import org.openqa.selenium.WebDriver;
import org.openqa.selenium.WebElement;
import org.openqa.selenium.firefox.FirefoxDriver;
import org.openqa.selenium.support.ui.ExpectedCondition;
import org.openqa.selenium.support.ui.Select;
import org.openqa.selenium.support.ui.WebDriverWait;

/**
 *
 * @author Gerson Groth
 */
public class WebCrawler {
    private WebDriver driver;
    private Data data;
    private Logger log;
    private WebDriverWait wait;
    private ArrayList<String> corridas;
    
    public void start() {
        driver = new FirefoxDriver();
        data = Data.getInstance();
        log = new Logger();
        corridas = new ArrayList<String>();
        try{
            login();
            explore();
            initSearch();
            getRunning();
            downloadActivities();
            validate();
        }catch(Exception e){
            e.printStackTrace();
        }
        finish();
        
    }

   
	private void login() {
        log.log("Abrindo página de login");
                
        driver.get("https://connect.garmin.com/signin");
        
        WebElement login = driver.findElement(By.id("login:loginUsernameField"));
        WebElement pass = driver.findElement(By.id("login:password"));
        WebElement button = driver.findElement(By.id("login:signInButton"));
        
        log.log("Efetuando login com o usuário " + data.getUserName());
        
        login.sendKeys(data.getUserName());
        pass.sendKeys(data.getPassword());
        button.click();
    }

    private void explore() {
        log.log("Abrindo página de busca");
        driver.get("http://connect.garmin.com/explore");
        
        wait  = new WebDriverWait(driver, 20);
        
        waiting();
        
    }

    private void waiting() {
        WebElement myDynamicElement;
        
        try{
            myDynamicElement = wait
                .until(new ExpectedCondition<WebElement>(){
                public WebElement apply(WebDriver d) {
                    WebElement element = d.findElement(By.id("_viewRoot:status.start"));
                    if(element == null) return null;
                    else{
                        if(element.isDisplayed()) return element;
                        else return null;
                    }
                }});
        }catch(Exception e){}
        try{
            myDynamicElement = wait
                .until(new ExpectedCondition<WebElement>(){
                public WebElement apply(WebDriver d) {
                    WebElement element = d.findElement(By.id("_viewRoot:status.start"));
                    if(element == null) return null;
                    else{
                        if(!element.isDisplayed()) return element;
                        else return null;
                    }
                }});
        }catch(Exception e){}
    }

    private void initSearch() {
        WebElement keyword = driver.findElement(By.id("exploreSearchForm:keyword"));
        WebElement location = driver.findElement(By.id("exploreSearchForm:location"));
        WebElement activityType = driver.findElement(By.id("exploreSearchForm:activityType"));
        WebElement eventType = driver.findElement(By.id("exploreSearchForm:eventType"));
        WebElement timePeriod = driver.findElement(By.id("exploreSearchForm:timePeriodSelect"));
        WebElement startDate = driver.findElement(By.id("exploreSearchForm:startDateCalendarInputDate"));
        WebElement endDate = driver.findElement(By.id("exploreSearchForm:endDateCalendarInputDate"));
        WebElement startDistance = driver.findElement(By.id("exploreSearchForm:activitySummarySumDistance-min"));
        WebElement endDistance = driver.findElement(By.id("exploreSearchForm:activitySummarySumDistance-max"));
        WebElement startTime = driver.findElement(By.id("exploreSearchForm:activitySummarySumDuration-min"));
        WebElement endTime = driver.findElement(By.id("exploreSearchForm:activitySummarySumDuration-max"));
        WebElement startElevation = driver.findElement(By.id("exploreSearchForm:activitySummaryGainElevation-min"));
        WebElement endElevation = driver.findElement(By.id("exploreSearchForm:activitySummaryGainElevation-max"));
        WebElement displayName = driver.findElement(By.id("exploreSearchForm:username"));
        WebElement myActivitiesOnly = driver.findElement(By.id("exploreSearchForm:myActivities"));
        
        WebElement showFilters = driver.findElement(By.id("showFilters")).findElements(By.linkText("Show Filters")).get(0);
        WebElement search = driver.findElement(By.id("searchButton"));
        
        showFilters.click();
        
        if(!"".equals(data.getKeyword())){
            keyword.sendKeys(data.getKeyword());
        }
        
        if(!"".equals(data.getLocation())){
            location.clear();
            location.sendKeys(data.getLocation());
        }
        
        Select select = new Select(timePeriod);
        select.selectByValue(data.getTimePeriod());
        select = new Select(activityType);
        select.selectByValue(data.getActivityType());
        select = new Select(eventType);
        select.selectByValue(data.getEventType());       
        
        if(Constants.CUSTOM_DATE.equals(data.getTimePeriod())){
            JavascriptExecutor js = (JavascriptExecutor) driver;
            js.executeScript("document.getElementById('exploreSearchForm:startDateCalendarInputDate').removeAttribute('readonly');", "");
            js.executeScript("document.getElementById('exploreSearchForm:endDateCalendarInputDate').removeAttribute('readonly');", "");
            startDate.sendKeys(data.getDateInit());
            endDate.sendKeys(data.getDateEnd());
        }
        
        startDistance.sendKeys(data.getDistanceInit());
        endDistance.sendKeys(data.getDistanceEnd());
        
        startTime.sendKeys(data.getTimeInit());
        endTime.sendKeys(data.getTimeEnd());
        
        startElevation.sendKeys(data.getElevationInit());
        endElevation.sendKeys(data.getElevationEnd());
        
        displayName.sendKeys(data.getDisplayName());
        
        if(data.isMyActivitiesOnly()){
            myActivitiesOnly.click();
        }
      
        search.click();
        
//        showFilters.click();
    }

    private void getRunning() {
       int pagina = 1;
       
       WebElement next = null;
       
        
       
       do{
            log.log("");
            log.log("Iniciando página " + pagina);
            
            waiting();
            
            
            List<WebElement> elements = driver.findElements(By.className("rich-datascr-button"));
            for(WebElement e : elements){
                if(e.getText().equals("»")){
                    next = e;
                    break;
                }
            }
            
//            WebElement paginaAtual = driver.findElement(By.className("rich-datascr-act"));
//            
//            System.out.println("Página " + paginaAtual.getText());
//            
//            System.out.println(next.isEnabled());
            
//            WebElement nextPage = driver.findElements(By.className("rich-datascr-inact")).get(Integer.parseInt(paginaAtual.getText()));
            
//            if(next.getAttribute("class").contains("rich-datascr-button-dsbld")){
//                System.err.println("terminou");
//            }
            
            
            
            log.log("Listando atividades página " + pagina);
            
            List<WebElement> tableRows = driver.findElements(By.className("rich-table-row"));
            
            for(WebElement e : tableRows){
                WebElement resultsEntry = e.findElement(By.className("resultsEntry"));
                WebElement resultsTitle = resultsEntry.findElement(By.className("resultsTitle"));
                WebElement a = resultsTitle.findElement(By.tagName("a"));
                String[] activity = a.getAttribute("href").split("/");
                
                log.log("Activity " + activity[activity.length-1] + " - " + a.getText());
                
                corridas.add(a.getAttribute("href"));
            }
            
            pagina++;
            if(next != null){
                next.click();
            }
        }while(next != null && !(next.getAttribute("class").contains("rich-datascr-button-dsbld")));
       
       log.log("Não há mais atividades");
       log.log("Total de atividades " + corridas.size());
       log.log("");
        
    }

    private void downloadActivities() {
        log.log("Iniciando o download das atividades");
        
        for(String s : corridas){
            log.log("Fazendo o download da activity : " + s);
            
            try{
                driver.get(s);
                try{
            		WebElement sigIn = driver.findElement(By.className("nav-logged-in"));
            		if(sigIn == null){
            			login();
                		driver.get(s);
            		}
            	}catch(NoSuchElementException ne){
            		login();
            		driver.get(s);
            	}
                String[] ss = s.split("/");
                int activity = Integer.parseInt(ss[ss.length-1]);
                DownloadActivity.download(driver.getPageSource(), activity);
                DownloadActivity.setCookies(driver.manage().getCookies());
                DownloadActivity.downloadTcx(activity);
                DownloadActivity.downloadGpx(activity);
            }catch(Exception e){
                log.log("Erro ao fazer download: (" + s + ") ->" + e.getMessage());
            }
        }
        try{
        	DownloadActivity.downloadAll();
        }catch(Exception e){
        	log.log("Erro ao fazer download do xml contendo todas as activities");
        }
    }
    
    /**
   	 * 
   	 */
   	private void validate() {
   		log.log("Verificando se todos os arquivos foram baixados");
   		ArrayList<String> ler = FileManager.ler(Data.getInstance().getXmlFolder() + "activities.xml");
   		ArrayList<String> atividadesTcx = new ArrayList<String>();
   		ArrayList<String> atividadesXml = new ArrayList<String>();
   		ArrayList<String> atividadesGpx = new ArrayList<String>();
   		for(String s : ler){
   			if(s.contains("file=")){
   				String activity = s.split("\"")[1];
   				activity = activity.substring(0, activity.lastIndexOf('.'));
   				atividadesTcx.add(activity);
   				atividadesXml.add(activity);
   				atividadesGpx.add(activity);
   			}
   		}
   		
   	//conferir .gpx
   		File gpxFolder = new File(Data.getInstance().getGpxFolder());
   		File[] listGpx = gpxFolder.listFiles();
   		
   		if(listGpx != null){
	   		for(File f : listGpx){
	   			try{
		   			String extension = f.getName().substring(f.getName().lastIndexOf('.'));
		   			if(".gpx".equals(extension))
		   				atividadesGpx.remove(f.getName().substring(0, f.getName().lastIndexOf('.')));
		   		}catch(Exception e){
	   				e.printStackTrace();
	   			}
	   		}
	   		for(String s : atividadesGpx){
	        	int activity = Integer.parseInt(s.split("_")[1]);
	            log.log("Fazendo o download da activity : " + s);
	            String d = "http://connect.garmin.com/activity/"+s.split("_")[1];
	            log.log("Baixando novamente activity (gpx): " + d);
	            try{
	                driver.get(d);
	                try{
	            		WebElement sigIn = driver.findElement(By.className("nav-logged-in"));
	            		if(sigIn == null){
	            			login();
	                		driver.get(d);
	            		}
	            	}catch(NoSuchElementException ne){
	            		login();
	            		driver.get(d);
	            	}                
	                DownloadActivity.setCookies(driver.manage().getCookies());
	                DownloadActivity.downloadGpx(activity);
	            }catch(Exception e){
	                log.log("Erro ao fazer download: (" + d + ") ->" + e.getMessage());
	            }
	        }
   		}
   		
   		//conferir .tcx
   		File tcxFolder = new File(Data.getInstance().getTcxFolder());
   		File[] listTcx = tcxFolder.listFiles();
   		
   		if(listTcx != null){
	   		for(File f : listTcx){
	   			try{
		   			String extension = f.getName().substring(f.getName().lastIndexOf('.'));
		   			if(".tcx".equals(extension))
		   				atividadesTcx.remove(f.getName().substring(0, f.getName().lastIndexOf('.')));
	   			}catch(Exception e){
	   				e.printStackTrace();
	   			}
	   		}
	   		for(String s : atividadesTcx){
	        	int activity = Integer.parseInt(s.split("_")[1]);
	            log.log("Fazendo o download da activity : " + s);
	            String d = "http://connect.garmin.com/activity/"+s.split("_")[1];
	            log.log("Baixando novamente activity (tcx): " + d);
	            try{
	                driver.get(d);
	                try{
	            		WebElement sigIn = driver.findElement(By.className("nav-logged-in"));
	            		if(sigIn == null){
	            			login();
	                		driver.get(d);
	            		}
	            	}catch(NoSuchElementException ne){
	            		login();
	            		driver.get(d);
	            	}                
	                DownloadActivity.setCookies(driver.manage().getCookies());
	                DownloadActivity.downloadTcx(activity);
	            }catch(Exception e){
	                log.log("Erro ao fazer download: (" + d + ") ->" + e.getMessage());
	            }
	        }
   		}
   		
   		
   		
   		//conferir .xml
   		File xmlFolder = new File(Data.getInstance().getXmlFolder());
   		File[] listXml = xmlFolder.listFiles();
   		
   		if(listXml != null){
	   		for(File f : listXml){
	   			try{
		   			String extension = f.getName().substring(f.getName().lastIndexOf('.'));
		   			if(".xml".equals(extension))
		   				atividadesXml.remove(f.getName().substring(0, f.getName().lastIndexOf('.')));
		   		}catch(Exception e){
	   				e.printStackTrace();
	   			}
	   		}
	   		for(String s : atividadesXml){
	        	int activity = Integer.parseInt(s.split("_")[1]);
	            log.log("Fazendo o download da activity : " + s);
	            String d = "http://connect.garmin.com/activity/"+s.split("_")[1];
	            log.log("Baixando novamente activity (xml): " + d);
	            try{
	                driver.get(d);
	                try{
	            		WebElement sigIn = driver.findElement(By.className("nav-logged-in"));
	            		if(sigIn == null){
	            			login();
	                		driver.get(d);
	            		}
	            	}catch(NoSuchElementException ne){
	            		login();
	            		driver.get(d);
	            	}                
	                DownloadActivity.download(driver.getPageSource(), activity);
	            }catch(Exception e){
	                log.log("Erro ao fazer download: (" + d + ") ->" + e.getMessage());
	            }
	        }
   		}   		
   	}


    private void finish() {
        log.log("Finalizando aplicação");
        try{
            quit();
        }catch(Exception e){}
        System.exit(0);
    }
    
//    @AfterClass
    private void quit(){
        driver.quit();
    }

}

